<template>
	<el-scrollbar height="100%">
		<div class="image_box">
			<module_container title="获取图片:">
				<div class="get_pictures">
					<div class="row">
						<div
							class="btn"
							@click="get_local_click">
							获取本地图片
						</div>
						<div
							class="btn"
							@click="get_network_click">
							获取网络图片
						</div>
					</div>
					<div class="cv_box">
						<canvas
							id="my_canvas"
							:width="cvs_data.cvs_width"
							:height="cvs_data.cvs_height"></canvas>
						<el-input-number
							class="el_inp_num"
							v-model="cvs_data.scale"
							:step="cvs_data.scale_step"
							:min="cvs_data.min_scale"
							:max="cvs_data.max_scale"
							:precision="0"
							:step-strictly="true"
							size="large"
							@change="draw_img">
							<template #suffix>
								<span>%</span>
							</template>
							<template #decrease-icon>
								<el-icon size="20">
									<ZoomOut />
								</el-icon>
							</template>
							<template #increase-icon>
								<el-icon size="20">
									<ZoomIn />
								</el-icon>
							</template>
						</el-input-number>
					</div>
				</div>
			</module_container>
			<module_container title="图片处理:">
				<div class="processing">
					<div class="row">
						<div
							class="btn"
							:class="{ btn_disabled: file_path_list.length == 0 }"
							@click="negative">
							底片效果
						</div>
						<div
							class="btn"
							:class="{ btn_disabled: file_path_list.length == 0 }"
							@click="retro">
							复古效果
						</div>
					</div>
					<div class="row">
						<div
							class="btn"
							:class="{ btn_disabled: file_path_list.length == 0 }"
							@click="grayscale(0)">
							黑白效果(等权重算法)
						</div>
						<div
							class="btn"
							:class="{ btn_disabled: file_path_list.length == 0 }"
							@click="grayscale(1)">
							黑白效果(自定义权重)
						</div>
						<el-input-number
							v-model="grayscale_config[0]"
							:step-strictly="true"
							:min="0"
							:max="1"
							:step="0.1">
							<template #prefix>
								<span>r:</span>
							</template>
						</el-input-number>
						<el-input-number
							v-model="grayscale_config[1]"
							:step-strictly="true"
							:min="0"
							:max="1"
							:step="0.1">
							<template #prefix>
								<span>g:</span>
							</template>
						</el-input-number>
						<el-input-number
							v-model="grayscale_config[2]"
							:step-strictly="true"
							:min="0"
							:max="1"
							:step="0.1">
							<template #prefix>
								<span>b:</span>
							</template>
						</el-input-number>
					</div>
					<div class="row">
						<div
							class="btn"
							:class="{ btn_disabled: file_path_list.length == 0 }"
							@click="grayscale">
							黑白效果
						</div>
						<div
							class="btn"
							:class="{ btn_disabled: file_path_list.length == 0 }"
							@click="negative">
							底片效果
						</div>
					</div>
					<div class="row">
						<div
							class="btn"
							:class="{ btn_disabled: file_path_list.length <= 0 }"
							@click="previous">
							上一步
						</div>
						<div
							class="btn"
							:class="{ btn_disabled: file_path_list.length <= 0 }"
							@click="next">
							下一步
						</div>
						<div
							class="btn"
							:class="{ btn_disabled: file_path_list.length == 0 }"
							@click="save">
							保存
						</div>
					</div>
				</div>
			</module_container>
		</div>
	</el-scrollbar>
</template>

<script setup>
	import module_container from "@/components/module_container/index.vue";
	import { ElMessage, ElMessageBox } from "element-plus";
	import { ZoomOut, ZoomIn } from "@element-plus/icons-vue";
	import { my_message } from "@/utils/my_message/index.js";
	import { Events } from "@/utils/events_bus/index.js";
	import { ref, onMounted, reactive, onBeforeMount } from "vue";
	import imageUtils from "@/utils/image.js";
	import sharp from "sharp";
	import { useIndexStore } from "@/store/model/index";

	const store = useIndexStore();
	const msg = my_message();

	const file_path_list = ref([]);
	const what_step = ref(0);
	let file_list = [];
	let ctx = "";
	const cvs_data = reactive({
		cvs_width: 0, // canvas的像素宽度
		cvs_height: 0, // canvas的像素高度
		scale: 100,
		scale_step: 10, // 每次滚轮的缩放比例变化
		min_scale: 10, // 最小缩放比例
		max_scale: 1000, // 最大缩放比例
		start_x: null,
		start_y: null,
		img_width: 0, // 当前缩放后图片的像素宽度
		img_height: 0, // 当前缩放后图片的像素高度
		source_image_width: 0, // 原始图片的像素宽度
		source_image_height: 0, // 原始图片的像素高度
	});
	// 平移参数
	let isDragging = false;
	let lastX = 0;
	let lastY = 0;
	const grayscale_config = ref([0, 0, 0]); // 自定义权重

	onBeforeMount(() => {
		file_list = [...store.config.file_list];
	});

	onMounted(() => {
		const canvas = document.getElementById("my_canvas");
		cvs_data.cvs_width = canvas.clientWidth;
		cvs_data.cvs_height = canvas.clientHeight;
		ctx = canvas.getContext("2d", { willReadFrequently: true });
		ctx.imageSmoothingEnabled = true; // 关闭平滑
		ctx.imageSmoothingQuality = "high"; // 提高平滑质量
		// 鼠标滚轮事件
		canvas.addEventListener("wheel", function (e) {
			if (file_path_list.value.length == 0) {
				return;
			}
			if (is_mouse_over_image(e.clientX, e.clientY, canvas)) {
				e.preventDefault();
				const delta = -e.deltaY;
				let new_scale =
					delta > 0
						? cvs_data.scale + cvs_data.scale_step
						: cvs_data.scale - cvs_data.scale_step;
				// 限制缩放范围
				cvs_data.scale = Math.min(
					Math.max(new_scale, cvs_data.min_scale),
					cvs_data.max_scale
				);
				draw_img();
			}
		});
		// 鼠标拖动平移图片
		canvas.addEventListener("mousedown", function (e) {
			if (is_mouse_over_image(e.clientX, e.clientY, canvas)) {
				isDragging = true; // 标记开始拖动
				lastX = e.clientX; // 记录鼠标按下时的 X 坐标
				lastY = e.clientY; // 记录鼠标按下时的 Y 坐标
			}
		});

		canvas.addEventListener("mousemove", function (e) {
			if (is_mouse_over_image(e.clientX, e.clientY, canvas)) {
				canvas.style.cursor = isDragging ? "grabbing" : "grab";
			} else {
				canvas.style.cursor = "default";
			}
			if (isDragging) {
				// 检查是否处于拖动状态
				const dx = e.clientX - lastX; // 计算 X 方向移动距离
				const dy = e.clientY - lastY; // 计算 Y 方向移动距离

				cvs_data.start_x += dx; // 更新 X 方向的平移量
				cvs_data.start_y += dy; // 更新 Y 方向的平移量

				lastX = e.clientX; // 更新上一次鼠标位置（X）
				lastY = e.clientY; // 更新上一次鼠标位置（Y）

				draw_img(); // 重新绘制图片（应用新的平移量）
			}
		});

		canvas.addEventListener("mouseup", function () {
			isDragging = false; // 标记拖动结束
		});
		// 防止鼠标离开 Canvas 时卡住
		canvas.addEventListener("mouseleave", function () {
			isDragging = false; // 如果鼠标移出 Canvas，强制结束拖动
		});
	});

	const get_local_click = async () => {
		init_cvs(); // 初始化数据
		const path = await Events.send_reply("open_dialog", { list: file_list });
		if (path == null) {
			return;
		}
		file_path_list.value.push(path);
		get_source_image_size();
		draw_img();
	};
	const get_network_click = async () => {
		ElMessageBox.prompt("请输入图片URL", "获取网络图片", {
			confirmButtonText: "确定",
			cancelButtonText: "取消",
			inputPattern: new RegExp(`\\.(${file_list.join("|")})$`, "i"),
			inputErrorMessage: "请输入正确的图片URL",
		})
			.then(async ({ value }) => {
				msg.msg_success("正在下载图片...");
				try {
					const response = await fetch(
						`http://localhost:3000/proxy-image?url=${encodeURIComponent(value)}`
					);

					const { contentType, data: base64Data } = await response.json();
					const path = `data:${contentType};base64,${base64Data}`;
					if (path == null) {
						return;
					}
					init_cvs(); // 初始化数据
					file_path_list.value.push(path);
					get_source_image_size();
					draw_img();
				} catch (err) {
					console.error("Error fetching image:", err);
					throw err;
				}
			})
			.catch(() => {
				msg.msg_warning("输入已取消");
			});
	};

	const get_source_image_size = () => {
		const img = new Image();
		img.onload = function () {
			cvs_data.source_image_width = img.width; // 原始图片的像素宽度
			cvs_data.source_image_height = img.height; // 原始图片的像素高度
			let canvas = document.createElement("canvas");
			canvas.width = cvs_data.source_image_width;
			canvas.height = cvs_data.source_image_height;
			let ctx = canvas.getContext("2d");
			ctx.drawImage(
				img,
				0,
				0,
				cvs_data.source_image_width,
				cvs_data.source_image_height
			);
			let dataURL = canvas.toDataURL();
			file_path_list.value[what_step.value] = dataURL;
			canvas = null;
			ctx = null;
		};
		img.src = file_path_list.value[what_step.value]; // 设置图像源
	};

	const draw_img = () => {
		const img = new Image();
		img.onload = function () {
			// 计算绘制图片的尺寸
			const img_width = Math.round(
				(cvs_data.source_image_width * cvs_data.scale) / 100
			);
			const img_height = Math.round(
				(cvs_data.source_image_height * cvs_data.scale) / 100
			);
			cvs_data.img_width = img_width;
			cvs_data.img_height = img_height;
			if (cvs_data.start_x == null || cvs_data.start_y == null) {
				if (
					img_width > cvs_data.cvs_width &&
					img_height > cvs_data.cvs_height
				) {
					cvs_data.start_x = 0;
					cvs_data.start_y = 0;
				} else if (
					img_width > cvs_data.cvs_width &&
					img_height < cvs_data.cvs_height
				) {
					cvs_data.start_x = 0;
					cvs_data.start_y = (cvs_data.cvs_height - img_height) / 2;
				} else if (
					img_width < cvs_data.cvs_width &&
					img_height > cvs_data.cvs_height
				) {
					cvs_data.start_x = (cvs_data.cvs_width - img_width) / 2;
					cvs_data.start_y = 0;
				} else {
					cvs_data.start_x = (cvs_data.cvs_width - img_width) / 2;
					cvs_data.start_y = (cvs_data.cvs_height - img_height) / 2;
				}
			}
			// 清空画布
			ctx.clearRect(0, 0, cvs_data.cvs_width, cvs_data.cvs_height);
			// 绘制图像
			ctx.drawImage(
				img,
				cvs_data.start_x,
				cvs_data.start_y,
				img_width,
				img_height
			);
		};
		img.src = file_path_list.value[what_step.value]; // 设置图像源
	};
	const init_cvs = () => {
		cvs_data.img_width = 0;
		cvs_data.img_height = 0;
		cvs_data.source_image_width = 0;
		cvs_data.source_image_height = 0;
		cvs_data.scale = 100;
		cvs_data.start_x = null;
		cvs_data.start_y = null;
		isDragging = false;
		lastX = 0;
		lastY = 0;
		what_step.value = 0;
		file_path_list.value = [];
		// 清空画布
		ctx.clearRect(0, 0, cvs_data.cvs_width, cvs_data.cvs_height);
	};
	// 检查鼠标是否在图片区域内
	const is_mouse_over_image = (clientX, clientY, canvas) => {
		const rect = canvas.getBoundingClientRect();
		const mouseX = clientX - rect.left;
		const mouseY = clientY - rect.top;

		return (
			mouseX >= cvs_data.start_x &&
			mouseX <= cvs_data.start_x + cvs_data.img_width &&
			mouseY >= cvs_data.start_y &&
			mouseY <= cvs_data.start_y + cvs_data.img_height
		);
	};

	const get_image_data = () => {
		let image_data = ctx.getImageData(
			cvs_data.start_x,
			cvs_data.start_y,
			cvs_data.img_width,
			cvs_data.img_height
		);
		return image_data;
	};
	// 灰度图
	const grayscale = type => {
		let path;
		if (type == 0) {
			path = imageUtils.grayscale(get_image_data()).get_dase64_image();
		} else if (type == 1) {
			path = imageUtils
				.grayscale(get_image_data(), grayscale_config.value)
				.get_dase64_image();
		}
		if (path == null) {
			msg.msg_error("灰度失败!");
			return;
		}
		file_path_list.value.push(path);
		what_step.value = file_path_list.value.length - 1;
		draw_img();
	};
	// 复古
	const retro = () => {
		const path = imageUtils.retro(get_image_data()).get_dase64_image();
		if (path == null) return;
		file_path_list.value.push(path);
		what_step.value = file_path_list.value.length - 1;
		draw_img();
	};
	// 底片
	const negative = () => {
		const path = imageUtils.negative(get_image_data()).get_dase64_image();
		if (path == null) return;
		file_path_list.value.push(path);
		what_step.value = file_path_list.value.length - 1;
		draw_img();
	};

	const previous = () => {
		what_step.value--;
		if (what_step.value < 0) {
			what_step.value++;
			msg.msg_warning("已经是第一张图片了!");
		} else {
			draw_img();
		}
	};

	const next = () => {
		what_step.value++;
		if (what_step.value <= file_path_list.value.length - 1) {
			draw_img();
		} else {
			what_step.value--;
			msg.msg_warning("已经是最后一张图片了!");
		}
	};

	const save = async () => {
		const save_path = await Events.send_reply("get_save_path");
		console.log(save_path);
		if (save_path == null) {
			return;
		}

		// save_file
		const msg = await Events.send_reply("save_file", {
			base64_data: file_path_list.value[what_step.value],
			output_dir: save_path,
			file_extension: "ico",
			// width: cvs_data.source_image_width,
			// height: cvs_data.source_image_height,
			width: cvs_data.img_width,
			height: cvs_data.img_height,
		});
		console.log(msg, cvs_data.img_width, cvs_data.img_height);
	};
</script>

<style lang="less" scoped>
	.image_box {
		width: 100%;
		height: 100%;
		padding: 15px;
		box-sizing: border-box;

		.get_pictures {
			display: flex;
			justify-content: center;
			flex-wrap: wrap;

			.row {
				width: 100%;
				display: flex;

				.btn {
					&:nth-child(n + 2) {
						margin-left: 20px;
					}
				}
			}

			.cv_box {
				margin-top: 10px;
				width: 100%;
				height: 600px;
				border: var(--split-line);
				box-sizing: border-box;
				position: relative;

				#my_canvas {
					width: 100%;
					height: 100%;
				}

				.el_inp_num {
					position: absolute;
					top: 0;
					left: 0;
					z-index: 999;
				}
			}
		}

		.processing {
			display: flex;
			justify-content: center;
			flex-wrap: wrap;

			.row {
				width: 100%;
				display: flex;

				&:nth-child(n + 2) {
					margin-top: 10px;
				}

				.btn {
					&:nth-child(n + 2) {
						margin-left: 20px;
					}
				}

				.el-input-number {
					margin-left: 20px;
				}
			}
		}
	}
</style>
